package com.ferrocarril;

import com.ferrocarril.objects.Arista;
import com.ferrocarril.objects.Grafo;
import com.ferrocarril.objects.Nodo;
import com.ferrocarril.util.Shuffle;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author David Navarro M
 */
public class Ferrocarril {

    static String dataGraph;
    static Grafo grafo;
    static Map<String, Integer> mapRoutes;

    /**
     * Metodo de creacion del grafo con sus nodos y relaciones.
     * @param initData EJ: AB5, BC4, CD8, DC8, DE6, AD5, CE2, EB3, AE7
     */
    private static void init() {
        grafo = new Grafo();

        /* CREAMOS LOS NODOS Y LAS ARISTAS DE ACUERDO A LOS DATOS INICIALES */
        String[] routes = dataGraph.split(",");
        for (int i = 0; i < routes.length; i++) {
            String route = routes[i].trim();

            Nodo inicio = new Nodo(route.substring(0, 1));
            grafo.addNodo(inicio);

            Nodo fin = new Nodo(route.substring(1, 2));
            grafo.addNodo(fin);

            grafo.getListAristas().add(new Arista(grafo.findNodo(inicio.getNombre()), grafo.findNodo(fin.getNombre()), Integer.parseInt(route.substring(2))));
        }
        
        loadMapRoutes();
    }
    
    /**
     * Se carga el mapa con las rutas del grafo
     */
    private static void loadMapRoutes() {
        String vertices = "";
        for (Nodo nodo : grafo.getListaNodo()) {
            vertices += nodo.getNombre();
        }
        
        Shuffle.shuffle(vertices+vertices);
        
        mapRoutes = new HashMap<String, Integer>();
        for (String cadena : Shuffle.palabras) {
            String temp = cadena;
            Integer costo = 0;
            
            while (temp.length() > 1) {
                boolean exists = false;

                if (grafo.findArista(temp.substring(0, 1), temp.substring(1, 2)) != null) {
                    costo += grafo.findArista(temp.substring(0, 1), temp.substring(1, 2)).getCosto();
                    exists = true;
                    temp = temp.substring(1);
                }

                if (!exists) {
                    costo = null;
                    break;
                }
            }
            
            if (costo != null) {
                mapRoutes.put(cadena, costo);
            }
        }
    }

    /**
     * METODO PARA CONSULTAR EL COSTO TOTAL DE UNA RUTA EN CASO DE QUE EXISTA
     * @param route EJ: ABCDE
     */
    public static String routeBetweenNodes(String route) {
        String result = "SIN RUTA";
        
        for (String ruta : mapRoutes.keySet()) {
            if (route.equals(ruta)) {
                result = mapRoutes.get(ruta).toString();
            }
        }
        
        return result;
    }

    /**
     * Basado en el mapa de rutas (mapRoutes) encuentra distintos caminos de acuerdo a los parametros de entrada.
     * 
     * @param from Nodo inicial
     * @param to Nodo final
     * @param minStops minimo de paradas entre nodos
     * @param maxStops maximo de paradas entre nodos
     * @param exactlyStops numero exacto de paradas entre nodos
     */
    public static String routes(String from, String to, Integer minStops, Integer maxStops, Integer exactlyStops, boolean lessCostRoute) {
        String result = "SIN RUTA";
        
        Map<String, Integer> validRoutes = new HashMap<String, Integer>();
        if (lessCostRoute) minStops = 1;
        
        for (String ruta : mapRoutes.keySet()) {
            if (ruta.substring(0, 1).equals(from) && ruta.substring(ruta.length()-1, ruta.length()).equals(to)) {
                String temp = ruta.substring(1, ruta.length());
                
                if (minStops != null) {
                    if (temp.length() > minStops) {
                        validRoutes.put(ruta, mapRoutes.get(ruta));
                    }
                } else if (maxStops != null) {
                    if (temp.length() <= maxStops) {
                        validRoutes.put(ruta, mapRoutes.get(ruta));
                    }
                } else if (exactlyStops != null) {
                    if (temp.length() == exactlyStops) {
                        validRoutes.put(ruta, mapRoutes.get(ruta));
                    }
                }
            }
        }
        
        if (lessCostRoute) {
            int cost = Integer.MAX_VALUE;
            String route = "";
            for (String ruta : validRoutes.keySet()) {
                if (validRoutes.get(ruta) < cost) {
                    cost = validRoutes.get(ruta);
                    route = ruta;
                } 
            }
            
            System.out.println(route + " - " + cost);
            result = cost+"";
        } else {
            for (String ruta : validRoutes.keySet()) {
                System.out.println(ruta + " - " + validRoutes.get(ruta));
            }
            
            result = validRoutes.size()+"";
        }
        
        return result;
    }

    public static void setDataGraph(String dataGraph) {
        Ferrocarril.dataGraph = dataGraph;
        init();
    }
    
}